﻿/**
 * Copyright(c) Live2D Inc. All rights reserved.
 *
 * Use of this source code is governed by the Live2D Open Software license
 * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
 */

#include "LAppDelegate.hpp"
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "LAppView.hpp"
#include "LAppPal.hpp"
#include "LAppDefine.hpp"
#include "LAppLive2DManager.hpp"
#include "LAppTextureManager.hpp"

using namespace Csm;
using namespace std;
using namespace LAppDefine;

namespace {
	LAppDelegate *s_instance = NULL;
}

LAppDelegate *LAppDelegate::GetInstance() {
	if (s_instance == NULL) {
		s_instance = new LAppDelegate();
	}

	return s_instance;
}

void LAppDelegate::ReleaseInstance() {
	if (s_instance != NULL) {
		delete s_instance;
	}

	s_instance = NULL;
}

bool LAppDelegate::Initialize(GLCore *window) {
	if (DebugLogEnable) {
		LAppPal::PrintLogLn("START");
	}

	// GLFWの初期化
	if (glfwInit() == GL_FALSE) {
		if (DebugLogEnable) {
			LAppPal::PrintLogLn("Can't initilize GLFW");
		}
		return GL_FALSE;
	}

	// Windowの生成_
	//_window = glfwCreateWindow(RenderTargetWidth, RenderTargetHeight, "SAMPLE", NULL, NULL);
	_window = window;
	if (_window == NULL) {
		if (DebugLogEnable) {
			LAppPal::PrintLogLn("Can't create GLFW window.");
		}
		glfwTerminate();
		return GL_FALSE;
	}

	// Windowのコンテキストをカレントに設定
	//glfwMakeContextCurrent(_window);
	_window->makeCurrent();
	glfwSwapInterval(1);

	if (glewInit() != GLEW_OK) {
		if (DebugLogEnable) {
			LAppPal::PrintLogLn("Can't initilize glew.");
		}
		glfwTerminate();
		return GL_FALSE;
	}

	//テクスチャサンプリング設定
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	//透過設定
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

	//コールバック関数の登録
	//glfwSetMouseButtonCallback(_window, EventHandler::OnMouseCallBack);
	//glfwSetCursorPosCallback(_window, EventHandler::OnMouseCallBack);

	// ウィンドウサイズ記憶
	//int width, height;
	//glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
	_windowWidth = _window->width();
	_windowHeight = _window->height();

	// Cubism SDK の初期化
	InitializeCubism();

	//AppViewの初期化
	_view->Initialize(_windowWidth, _windowHeight);

	return GL_TRUE;
}

void LAppDelegate::Release() {
	// Windowの削除
	//glfwDestroyWindow(_window);

	glfwTerminate();

	delete _textureManager;
	delete _view;

	// リソースを解放
	LAppLive2DManager::ReleaseInstance();

	//Cubism SDK の解放
	CubismFramework::Dispose();
}

//void LAppDelegate::Run()
//{
//	//メインループ
//	while (glfwWindowShouldClose(_window) == GL_FALSE && !_isEnd)
//	{
//		int width, height;
//		glfwGetWindowSize(LAppDelegate::GetInstance()->GetWindow(), &width, &height);
//
//
//		// 時間更新
//		LAppPal::UpdateTime();
//
//		// 画面の初期化
//		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//		glClearDepth(1.0);
//
//		//描画更新
//		_view->Render();
//
//		// バッファの入れ替え
//		glfwSwapBuffers(_window);
//
//		// Poll for and process events
//		glfwPollEvents();
//	}
//
//	Release();
//
//	LAppDelegate::ReleaseInstance();
//}

void LAppDelegate::resize(int width, int height) {
	if ((_windowWidth != width || _windowHeight != height) && width > 0 && height > 0) {
		//AppViewの初期化
		_view->Initialize(width, height);
		// スプライトサイズを再設定
		_view->ResizeSprite();
		// サイズを保存しておく
		_windowWidth = width;
		_windowHeight = height;

		// ビューポート変更
		glViewport(0, 0, width, height);
	} else {
		glViewport(0, 0, width, height);
	}
}

void LAppDelegate::update() {
	// 時間更新
	LAppPal::UpdateTime();

	// 画面の初期化
	//glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // TODO
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // TODO
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearDepth(1.0);

	//描画更新
	_view->Render();
}

LAppDelegate::LAppDelegate() : _cubismOption(),
                               _window(NULL),
                               _captured(false),
                               _mouseX(0.0f),
                               _mouseY(0.0f),
                               _isEnd(false),
                               _windowWidth(0),
                               _windowHeight(0) {
	_view = new LAppView();
	_textureManager = new LAppTextureManager();
}

LAppDelegate::~LAppDelegate() {
}

void LAppDelegate::InitializeCubism() {
	//setup cubism
	_cubismOption.LogFunction = LAppPal::PrintMessage;
	_cubismOption.LoggingLevel = LAppDefine::CubismLoggingLevel;
	_cubismOption.LoadFileFunction = LAppPal::LoadFileAsBytes;
	_cubismOption.ReleaseBytesFunction = LAppPal::ReleaseBytes;
	Csm::CubismFramework::StartUp(&_cubismAllocator, &_cubismOption);

	//Initialize cubism
	CubismFramework::Initialize();

	//load model
	LAppLive2DManager::GetInstance();

	//default proj
	CubismMatrix44 projection;

	LAppPal::UpdateTime();
}

void LAppDelegate::OnMouseCallBack(GLFWwindow *window, int button, int action, int modify) {
	if (_view == NULL) {
		return;
	}
	if (GLFW_MOUSE_BUTTON_LEFT != button) {
		return;
	}

	if (GLFW_PRESS == action) {
		_captured = true;
		_view->OnTouchesBegan(_mouseX, _mouseY);
	} else if (GLFW_RELEASE == action) {
		if (_captured) {
			_captured = false;
			_view->OnTouchesEnded(_mouseX, _mouseY);
		}
	}
}

void LAppDelegate::OnMouseCallBack(GLFWwindow *window, double x, double y) {
	_mouseX = static_cast<float>(x);
	_mouseY = static_cast<float>(y);

	if (!_captured) {
		return;
	}
	if (_view == NULL) {
		return;
	}

	_view->OnTouchesMoved(_mouseX, _mouseY);
}
